﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using ShareIt_MVC3.Models;


namespace TestProject
{
    /// <summary>
    /// Unit-tests für die Klasse clsUserCollection.cs
    /// </summary>
    [TestClass]
    public class UnitTestUser
    {
        public UnitTestUser()
        {
            // leerer Konstruktor
        }

        private TestContext testContextInstance;

        /// <summary>
        ///Ruft den Textkontext mit Informationen über
        ///den aktuellen Testlauf sowie Funktionalität für diesen auf oder legt diese fest.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region Zusätzliche Testattribute
        //
        // Sie können beim Schreiben der Tests folgende zusätzliche Attribute verwenden:
        //
        // Verwenden Sie ClassInitialize, um vor Ausführung des ersten Tests in der Klasse Code auszuführen.
        // [ClassInitialize()]
        // public static void MyClassInitialize(TestContext testContext) { }
        //
        // Verwenden Sie ClassCleanup, um nach Ausführung aller Tests in einer Klasse Code auszuführen.
        // [ClassCleanup()]
        // public static void MyClassCleanup() { }
        //
        // Mit TestInitialize können Sie vor jedem einzelnen Test Code ausführen. 
        // [TestInitialize()]
        // public void MyTestInitialize() { }
        //
        // Mit TestCleanup können Sie nach jedem einzelnen Test Code ausführen.
        // [TestCleanup()]
        // public void MyTestCleanup() { }
        //
        #endregion

        /// <summary>
        /// Test: Read all Users, insert one, search it in list, delete it again
        /// </summary>
        [TestMethod]
        public void TestInsertDeleteUser()
        {
            int i, c1, c2, c3;
            Console.WriteLine("TestInsertDeleteUser(): Start");
            List<User> UserList;
            UserCollection Users = new UserCollection();
            User testUser = new User()
            {
                Username = "TestUsername",
                Name = "TestName",
                Surname = "TestSurname",
                Address = "TestAddress",
                City = "TestCity",
                ZIP = "12345",
                EMail = "test@test.de",
                IsAdmin = false,
                Active = true,
                Password = "TestPassword",
                Credits = 1
            };
            
                // read User list
            UserList = Users.GetAllUsers();
            c1 = UserList.Count;
                // insert new User object
            i = Users.InsertUser(testUser);
            Assert.AreEqual(i, 1, "Insert failed");
            Console.WriteLine("TestInsertDeleteUser(): Insert");

                // read User list again and check if there is one more in list
            UserList = Users.GetAllUsers();
            c2 = UserList.Count;
            Assert.AreEqual(c1+1, c2);
                // look for User object that was just inserted and delete it again
            foreach (User p in UserList)
            {
                if (p.Username == "TestUsername")
                {
                    i = Users.DeleteUser(p);
                    Assert.AreEqual(i, 1, "delete Failed!");
                    Console.WriteLine("TestInsertDeleteUser(): Delete");
                }
            }
                // read User list again and check if there is one less in list
            UserList = Users.GetAllUsers();
            c3 = UserList.Count;
            Assert.AreEqual(c1, c3, "Count after Delete wrong!");
            Console.WriteLine("TestInsertDeleteUser(): End");
        }

        /// <summary>
        /// Test: Read all Users, insert one, update it, delete it again
        /// </summary>
        [TestMethod]
        public void TestInsertUpdateDeleteUser()
        {
            int i, c1, c2, c3, pid;
            List<User> UserList;
            UserCollection Users = new UserCollection();
            User testUser = new User()
            {
                Username = "TestUsername",
                Name = "TestName",
                Surname = "TestSurname",
                Address = "TestAddress",
                City = "TestCity",
                ZIP = "12345",
                EMail = "test@test.de",
                IsAdmin = false,
                Active = true,
                Password = "TestPassword",
                Credits = 1
            };

            UserList = Users.GetAllUsers();
            c1 = UserList.Count;
            i = Users.InsertUser(testUser);
            Assert.AreEqual(i, 1);
            UserList = Users.GetAllUsers();
            c2 = UserList.Count;
            Assert.AreEqual(c1 + 1, c2);
            foreach (User p in UserList)
            {
                if (p.Username == "TestUsername")
                {
                    pid = p.ID;
                    p.Address = "TestAddress2";
                    i = Users.UpdateUser(p);
                    Assert.AreEqual(i, 1);
                    testUser = Users.GetUserById(pid);
                    Assert.AreEqual(testUser.Username, "TestUsername");
                    Assert.AreEqual(testUser.Address, "TestAddress2");
                    i = Users.DeleteUser(testUser);
                    Assert.AreEqual(i, 1);
                }
            }

            UserList = Users.GetAllUsers();
            c3 = UserList.Count;
            Assert.AreEqual(c1, c3);
        }

        /// <summary>
        /// test: try to delete non-existent User
        /// </summary>
        [TestMethod]
        public void TestDeleteNonExistentUser()
        {
            int i, c1, c2, c3;
            List<User> UserList;

            Console.WriteLine("TestDeleteNonExistentUser(): Start");
            UserCollection Users = new UserCollection();
            User testUser = new User();
            testUser.Name = "TestName";
            testUser.Address = "TestAddress";


            UserList = Users.GetAllUsers();
            c1 = UserList.Count;
            foreach (User p in UserList)
            {
                if (p.Name == "TestName")
                {
                    Assert.Inconclusive("TestDeleteNonExistentUser(): User TestName exists already???");
                }
            }
            i = Users.DeleteUser(testUser);
            Assert.AreEqual(0, i, "TestDeleteNonExistentUser(): DeleteUser unexpected result");
            UserList = Users.GetAllUsers();
            c3 = UserList.Count;
            Assert.AreEqual(c1, c3, "TestDeleteNonExistentUser(): Count after Delete wrong!");
            Console.WriteLine("TestDeleteNonExistentUser(): End");

        }

        /// <summary>
        /// try to update non-existent User
        /// </summary>
        [TestMethod]
        public void TestUpdateNonExistentUser()
        {
            int i, c1, c2, c3;
            List<User> UserList;

            Console.WriteLine("TestUpdateNonExistentUser(): Start");
            UserCollection Users = new UserCollection();
            User testUser = new User()
            {
                Username = "TestUsername",
                Name = "TestName",
                Surname = "TestSurname",
                Address = "TestAddress",
                City = "TestCity",
                ZIP = "12345",
                EMail = "test@test.de",
                IsAdmin = false,
                Active = true,
                Password = "TestPassword",
                Credits = 1
            };

            UserList = Users.GetAllUsers();
            c1 = UserList.Count; 
            i = Users.UpdateUser(testUser);
            Assert.AreEqual(0, i, "TestUpdateNonExistentUser(): Update unexpected result");
            Console.WriteLine("TestDeleteNonExistentUser(): End");
        }

        [TestMethod]
        public void TestIncrementUserCredits()
        {
            UserCollection userColl = new UserCollection();
            User testUser = new User()
                                        {
                                            Username = "TestUsername",
                                            Name = "TestName",
                                            Surname = "TestSurname",
                                            Address = "TestAddress",
                                            City = "TestCity",
                                            ZIP = "12345",
                                            EMail = "test@test.de",
                                            IsAdmin = false,
                                            Active = true,
                                            Password = "TestPassword",
                                            Credits = 1
                                        };
            int i = userColl.InsertUser(testUser);
            Assert.AreEqual(1, i);

            User user = userColl.GetUserByUsername(testUser.Username);
            int currentCredits = user.Credits;

            int c = userColl.IncrementUserCredits(user);
            Assert.AreEqual(1, c);
            
            user = userColl.GetUserByUsername(testUser.Username);
            Assert.AreEqual(currentCredits + 1, user.Credits);

            // User cleanup
            userColl.DeleteUser(userColl.GetUserByUsername(testUser.Username));

            
        }

        [TestMethod]
        public void TestDecrementUserCredits()
        {
            UserCollection userColl = new UserCollection();
            User testUser = new User()
            {
                Username = "TestUsername",
                Name = "TestName",
                Surname = "TestSurname",
                Address = "TestAddress",
                City = "TestCity",
                ZIP = "12345",
                EMail = "test@test.de",
                IsAdmin = false,
                Active = true,
                Password = "TestPassword",
                Credits = 1
            };

            int i = userColl.InsertUser(testUser);
            Assert.AreEqual(1, i);

            User user = userColl.GetUserByUsername(testUser.Username);
            int currentCredits = user.Credits;

            int c = userColl.DecrementUserCredits(user);
            Assert.AreEqual(1, c);

            user = userColl.GetUserByUsername(testUser.Username);
            Assert.AreEqual(currentCredits - 1, user.Credits);

            // User cleanup
            userColl.DeleteUser(userColl.GetUserByUsername(testUser.Username));


        }
    }
}
